import { ContainerService } from "shared/component/container/ContainerService";
import EventBinder from "shared/component/event/EventBinder";
import InstanceMap from "shared/component/event/InstanceRemoveEvent";
import Log4R from "shared/component/log/Log4R";

const loginfo = Log4R.getLog('info');
export class AIServiceImpl extends ContainerService<Ctn.AIService, Ctn.AIEntity> implements Ctn.AIService {
    /** AI状态表 */
    protected AIStateMap = new InstanceMap<Ctn.character.HumanModel, Ctn.AI.AIState>()

    /** AI配置表 */
    protected AIConfigMap = new InstanceMap<Ctn.character.HumanModel, Ctn.AI.AICharacterEntity>()

    /** ai规则表 */
    private aiRolesMap = new Map<string, Ctn.AI.Role>()
    /** AI命令事件 */
    private AICommandEventBinder = new EventBinder<(event: Ctn.AI.AICommand) => void>();
    /** AI命令事件 */
    onAIcommandCall = this.AICommandEventBinder.bind();
    protected serverCalls: (keyof this)[] = [];
    protected serviceName: keyof Ctn.Services = "aIService";
    public run(): void {
        task.spawn(() => {
            while (true) {
                this.step();
                task.wait(0.1)
            }
        })
    }
    /** AI整体思考步骤 */
    private step() {
        // throw new Error("Method not implemented.");
        this.AIStateMap.forEach((state, model) => {
            if (state.areaActive) {
                if (state.thinkprocess <= 0) {//思考时间到
                    state.thinkprocess = state.currentThink;
                    this.AICommandEventBinder.callBack({
                        character: model,
                        act: {
                            act: 'move',
                            enable: false
                        }
                    })
                } else {//思考时间未到
                    state.thinkprocess -= 0.1
                }
            }
        })
    }


    /** npc模型添加事件绑定 */
    private npcCharacterAdd = new EventBinder<(AIEntity: Ctn.AI.AICharacterEntity) => void>()
    /** npc模型添加事件绑定 */
    onNpcCharacterAdd = this.npcCharacterAdd.bind()

    syncAIConfig(aiConfigs: Ctn.AI.AICharacterEntity[]) {
        // loginfo?.info(' this.AIConfigMap', aiConfig)
        aiConfigs.forEach(aiConfig => {
            /* 合并缓存AIrole */
            const role = aiConfig.role;
            if (role.id) {
                const roleInCache = this.aiRolesMap.get(role.id);
                if (roleInCache) {
                    aiConfig.role = roleInCache
                } else {
                    this.aiRolesMap.set(role.id, role)
                }
            }
            /* 初始化ai的配置 */
            if (aiConfig.character) {
                this.AIConfigMap.set(aiConfig.character, aiConfig);
                /* 初始化ai的状态 */
                this.AIStateMap.set(aiConfig.character, {
                    areaActive: false,
                    defaultThink: aiConfig.role.thinkTime,
                    currentThink: aiConfig.role.thinkTime,
                    thinkprocess: 0
                })
                this.setCharacter(aiConfig)
                this.npcCharacterAdd.callBack(aiConfig)
            }
        })

        // loginfo?.info(' this.AIConfigMap', aiConfig, this.AIConfigMap)
    }
    /** 切换区域 */
    onChangeArea(enterAreaEntity: Ctn.scence.EnterAreaEntity) {
        this.AIConfigMap.forEach((config, model) => {
            const state = this.AIStateMap.get(model)
            if (state) {
                if (config.areaName === enterAreaEntity.areaName) {
                    state.areaActive = true
                    this.AICommandEventBinder.callBack({
                        character: model,
                        act: {
                            act: 'anchored',
                            enable: false
                        }
                    })
                } else {
                    state.areaActive = false
                    this.AICommandEventBinder.callBack({
                        character: model,
                        act: {
                            act: 'anchored',
                            enable: true,
                            cframe: config.bornCframe
                        }
                    })
                }
            }

        })
    }
}